﻿namespace Reals.Parellel
{
  #region Using directives

  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Threading;

  #endregion
  /// <summary>
  /// 微过程时序循环(单元).
  /// </summary>
  public interface MicroCycling:IDisposable 
  {
    /// <summary>
    /// 同步等时面列表
    /// 中当前的等时面
    /// (即时钟嘀哒).
    /// </summary>
    /// <remarks>
    /// 在虚拟时间连续的系统中,
    /// 一个时钟嘀哒意味着在
    /// 当前处理单元中,依次表现
    /// 每个等时面上的并行性.
    /// 具体的说,我们认为在一个
    /// 时钟嘀哒中,不同的等时面
    /// 之间是顺序表现的,依次进
    /// 行的,也就是串行的,而等时
    /// 面次中的所有微过程都是
    /// 并行表现的.
    /// 然而,我们从宏观上观察的
    /// 结果将是所有等时面的循环
    /// 构成的稳定性,以及微过程
    /// 体现的并行性.
    /// 简单的说,我们将在宏观看到
    /// 稳定的,并行的时间连续系统
    /// 表象!
    /// </remarks>
    MicroProcess EntryProcess { get;}
    /// <summary>
    /// 判别当前对象是否已经被处置。
    /// </summary>
    bool IsDisposed { get;}
    /// <summary>
    /// 获取当前进行的等时面标识.
    /// </summary>
    int CurrentSyncLayer { get;}
    /// <summary>
    /// 判别当前循环是否具有等时面。
    /// </summary>
    bool HasMicroSynchings { get; }
    /// <summary>
    /// 获取当前时序循环中的所有等时面。
    /// </summary>
    IList<MicroSynching> MicroSynchings { get;}
    /// <summary>
    /// 创建等时面,并将它添加到时序单元.
    /// </summary>
    /// <returns>新创建的等时面.</returns>
    MicroSynching CreateSyncLayer(string name,params MicroProcess[] processes);
    /// <summary>
    /// 根据标识获得等时面.
    /// </summary>
    MicroSynching GetSyncLayer(string name);
    /// <summary>
    /// 加入微过程..
    /// </summary>
    /// <returns>
    /// 返回微过程加入到的等时面(可能和标识要求不同,
    /// 这是因为标识指定的等时面不能在此时创建).
    /// </returns>
    MicroSynching AddMicroProcess(string name, MicroProcess process);
    /// <summary>
    /// 在指定等时面删除微过程.
    /// </summary>
    /// <returns>返回微过程被删除的等时面.如果标识指定的等时面没有找到,那么返回null.</returns>
    MicroSynching RemoveMicroProcess(string name, MicroProcess process);
    /// <summary>
    /// 登记指定时序单元.
    /// </summary>
    MicroCycling Merge(MicroCycling cycling);
    /// <summary>
    /// 注销指定时序单元.
    /// </summary>
    MicroCycling Break(MicroCycling cycling);
    /// <summary>
    /// 扩展当前时序单元.
    /// </summary>
    /// <remarks>
    /// 扩展时序单元,意思是以当前
    /// 时序单元的层次结构为基础,
    /// 生成新的时序单元,并将新的
    /// 时序单元登记在当前时序单元的
    /// 同步方法上.
    /// </remarks>
    /// <returns>新生成的时序单元.</returns>
    MicroCycling WidenOut();
    /// <summary>
    /// 移除和目标相关的所有等时面。
    /// </summary>
    void RemoveTarget(object target);


  }


  /// <summary>
  /// 微过程时序单元的实现.
  /// </summary>
  public class MicroCyclingImpl : MicroCycling
  {
    #region Shortcuts
    public static MicroCycling it()
    {
      return new MicroCyclingImpl();
    }
    public static MicroCycling of(params MicroSynching[] layers)
    {
      return new MicroCyclingImpl(layers);
    }
    public static MicroCycling of(int initLayers)
    {
      return new MicroCyclingImpl(initLayers);
    }
    #endregion
    #region Fields
    protected int currentSyncLayer = -1;
    protected MicroProcess currentProcess = null;
    protected bool isDisposed = false;
    protected List<MicroSynching> microSynchings = null;
    #endregion
    #region Properties
    public virtual int CurrentSyncLayer
    {
      get { return this.currentSyncLayer; }
    }
    public virtual MicroProcess EntryProcess
    {
      get { return this.currentProcess; }
    }

    public virtual bool HasMicroSynchings
    {
      get
      {
        return this.microSynchings != null && this.microSynchings.Count > 0;
      }
    }
    public virtual IList<MicroSynching> MicroSynchings
    {
      get
      {
        return this.microSynchings == null ?
          this.microSynchings = new List<MicroSynching>() :
          this.microSynchings;
      }
    }

    public virtual bool IsDisposed
    {
      get
      {
        return this.isDisposed;
      }
    }
    #endregion
    #region Constructors
    /// <summary>
    /// 扩展到可以分裂.
    /// 用于辅助MicroExistent.
    /// </summary>
    public MicroCyclingImpl() : base() { this.OnInitialize(); }
    public MicroCyclingImpl(int initLayers) { }
    public MicroCyclingImpl(params MicroSynching[] layers)
    { 
      this.OnInitialize();
      if (layers != null && this.MicroSynchings!=null)
      {
        this.microSynchings.AddRange(layers);
      }
    }
    ~MicroCyclingImpl()
    {
      this.Dispose();
    }
    #endregion
    #region Methods
    public virtual MicroSynching AddMicroProcess(string name, MicroProcess process)
    {
      MicroSynching ilayer = this.GetSyncLayer(name);
      if (ilayer == null)
      {
        ilayer = this.CreateSyncLayer(name, process);
      }
      else
      {
        ilayer.Add(process);
      }
      return ilayer;
    }
    public virtual MicroSynching RemoveMicroProcess(string name, MicroProcess process)
    {
      MicroSynching ilayer = this.GetSyncLayer(name);
      if (ilayer != null)
      {
        ilayer.Remove(process);
      }
      return ilayer;
    }

    public virtual MicroSynching GetSyncLayer(string name)
    {
      if (name != null && this.HasMicroSynchings)
      {
        foreach (MicroSynching syncher in this.MicroSynchings)
        {
          if (syncher != null && syncher.Name == name)
          {
            return syncher;
          }
        }
      }
      return null;
    }
    public virtual MicroSynching CreateSyncLayer(string name, params MicroProcess[] processes)
    {
      MicroSynching syncher = null;

      this.MicroSynchings.Add(syncher = MicroSynchingImpl.of(name,processes));

      return syncher;
    }
    public virtual MicroCycling Merge(MicroCycling cycling)
    {
      if (cycling!=null)
      {
        this.currentProcess += cycling.EntryProcess;
      }
      return cycling;
    }
    public virtual MicroCycling Break(MicroCycling cycling)
    {
      if (cycling != null)
      {
        this.currentProcess -= cycling.EntryProcess;
      }
      return cycling;
    }
    public virtual MicroCycling WidenOut()
    {
      return this.Merge(this.CreateCycling());
    }
    public virtual void RemoveTarget(object target)
    {
      if (this.HasMicroSynchings)
      {
        foreach (MicroSynching layer in this.MicroSynchings)
        {
          if (layer != null)
          {
            layer.RemoveTarget(target);
          }
        }
      }
    }




    protected virtual void OnInitialize()
    {
      this.currentProcess += this.SynchLayer;
    }
    protected virtual bool SynchLayer()
    {
      this.OnSynchCurrentLayer();

      return true;
    }
    protected virtual void OnSynchCurrentLayer()
    {
      this.OnSynchCurrentLayer(this.GetNextLayer()); 
    }
    protected virtual void OnSynchCurrentLayer(MicroSynching layer)
    {
      if (layer != null)
      {
        layer.Tick();
      }
    }
    protected virtual MicroSynching GetNextLayer()
    {
      this.currentSyncLayer =
        this.HasMicroSynchings ?
        ((this.currentSyncLayer + 1 >= this.MicroSynchings.Count) ? 0 : this.currentSyncLayer + 1) :
        -1;

      return this.currentSyncLayer >= 0 ? this.MicroSynchings[this.currentSyncLayer] : null;
    }
    protected virtual MicroCycling CreateCycling()
    {
      return new MicroCyclingImpl();
    }

    public virtual void Dispose()
    {
      if (!this.isDisposed)
      {
        GC.SuppressFinalize(this);

        this.currentProcess = null;
        this.currentSyncLayer = -1;
        if (this.HasMicroSynchings)
        {
          foreach (MicroSynching synching in this.MicroSynchings)
          {
            if (synching != null)
            {
              synching.Dispose();
            }
          }
        }
        this.MicroSynchings.Clear();
        this.isDisposed = true;
      }
    }
    #endregion
  }
}